#include <stdio.h>
#include <conio.h>
#include <iostream>
#include "..\Engine\Vertex.h"
#include "..\Engine\Game\fwModelTextStore.h"

#define ROWS 128
#define COLS 128
#define TERRAIN_SCALE 1.0f

class WriteModel
{
public:
	Vertex* vertices;
	FWuint vertexCount;
	FWuint* indices;
	FWuint indexCount;
public:
	int GenVertices(int iRow, int iCol, float fDx, float fDz);
	int GenIndices(int iRow, int iCol);
	int GenNormal(int AID, int BID, int CID);
	void WriteFile(char* fileName);
	void WriteVector(FILE* f, void* vector, int type);
};
int WriteModel::GenVertices(int iRow, int iCol, float fDx, float fDz)
{
	//Setup size of terrain
	float fWidth = (iCol - 1) * fDx;
	float fHeight = (iRow - 1) * fDz;

	float fOffsetX = -fWidth / 2.0f;
	float fOffsetZ = -fHeight / 2.0f;

	//genvertex
	vertexCount = iRow * iCol;
	vertices = new Vertex[vertexCount];
	int idx = 0;
	for (int i = 0; i<iRow; i++)
	{
		for (int j = 0; j<iCol; j++)
		{
			vertices[idx].Position.x = j*fDx + fOffsetX;
			vertices[idx].Position.y = 0.0f;// m_HeightMapData.HeightData[idx];
			vertices[idx].Position.z = i*fDz + fOffsetZ;

			vertices[idx].Coordinate.x = (vertices[idx].Position.x - fOffsetX) / fWidth * TERRAIN_SCALE;
			vertices[idx].Coordinate.y = (vertices[idx].Position.z - fOffsetZ) / fWidth * TERRAIN_SCALE;
			idx++;
		}
	}

	return vertexCount;
}
int WriteModel::GenIndices(int iRow, int iCol)
{
	//Tong so tam giac = 2 * so o
	int iTrigCount = (iRow - 1) * (iCol - 1) * 2;
	//Tong so index = 3 * tong tam giac
	indexCount = iTrigCount * 3;

	//Tao tra mot ma tran co n phan tu
	//moi phan tu dai dien 1 tam giac
	indices = new FWuint[indexCount];

	int idx = 0;
	for (int i = 0; i<iRow - 1; ++i)
	{
		for (int j = 0; j<iRow - 1; ++j)
		{
			//First triangle of cell; ABC
			indices[idx++] = i*iCol + j;      //A
			indices[idx++] = i*iCol + (j + 1);//B
			indices[idx++] = (i + 1)*iCol + j;//C
			GenNormal(indices[idx - 3], indices[idx - 2], indices[idx - 1]);

			//Second triangle of cell; CBD
			indices[idx++] = (i + 1)*iCol + j;     //C
			indices[idx++] = i*iCol + (j + 1);     //B
			indices[idx++] = (i + 1)*iCol + (j + 1);//D
			GenNormal(indices[idx - 3], indices[idx - 2], indices[idx - 1]);
		}
	}

	for (int i = 0; i<iRow; i++)
	{
		for (int j = 0; j<iCol; j++)
		{
			vertices[j*iCol + j].Normal = (vertices[j*iCol + j].Normal / 6).Normalize();
		}
	}

	return indexCount;
}
int WriteModel::GenNormal(int AID, int BID, int CID)
{
	Vector3 A = vertices[AID].Position;
	Vector3 B = vertices[BID].Position;
	Vector3 C = vertices[CID].Position;

	Vector3 AB = B - A;
	Vector3 AC = B - A;
	Vector3 BA = A - B;
	Vector3 BC = C - A;
	Vector3 CA = A - C;
	Vector3 CB = B - C;

	vertices[AID].Normal += AB.Cross(AC);
	vertices[BID].Normal += BA.Cross(BC);
	vertices[CID].Normal += CA.Cross(CB);

	return 0;
}
void WriteModel::WriteFile(char* fileName)
{
	FILE * f = fopen(fileName, "wb");
	if (f == NULL)
		return;

	for (unsigned int i = 0; i < vertexCount; i++)
	{
		fprintf(f, "#%d\tpos:", i);
		WriteVector(f, &vertices[i].Position, 3);
		fprintf(f, "uv:", i);
		WriteVector(f, &vertices[i].Coordinate, 2);
		fprintf(f, "nrm:", i);
		WriteVector(f, &vertices[i].Normal, 3);
		fprintf(f, "bnrm:", i);
		WriteVector(f, &vertices[i].BiNormal, 3);
		fprintf(f, "tgt:", i);
		WriteVector(f, &vertices[i].Tangent, 3);
		fprintf(f, "\n");
	}

	for (unsigned int i = 0; i < indexCount; i += 3)
	{
		fprintf(f, "%d\t%d\t%d\n", indices[i], indices[i + 1], indices[i + 2]);
	}

	fclose(f);
}
void WriteModel::WriteVector(FILE* f, void* vector, int type)
{
	Vector2 v2;
	Vector3 v3;
	Vector4 v4;
	switch (type)
	{
	case 2:
		v2 = *((Vector2*)vector);
		fprintf(f, "[%f,%f];\t", v2.x, v2.y);
		break;
	case 3:
		v3 = *((Vector3*)vector);
		fprintf(f, "[%f,%f,%f];\t", v3.x, v3.y, v3.z);
		break;
	case 4:
		v4 = *((Vector4*)vector);
		fprintf(f, "[%f,%f,%f,%f];\t", v4.x, v4.y, v4.z, v4.w);
		break;
	default:
		break;
	}
}

int main()
{
	ModelTextHelper helper = ModelTextHelper();
	int key;
	char input[256];
	char output[256];
	FILE *fi, *fo;
	WriteModel write;
	Vertex *vertices = NULL;
	FWuint vertexCount = 0;
	FWuint *indices = NULL;
	FWuint indexCount = 0;
	printf("Chon che do chay (0:terrain-1:convert): "); scanf("%d", &key);

	switch (key)
	{
	case 0:
		printf("Out put: "); scanf("%s", &output);
		write = WriteModel();
		write.GenVertices(ROWS, COLS, 0.5f, 0.5f);
		write.GenIndices(ROWS, COLS);

		fi = fopen(output, "wb");
		if (!fi)
			return -1;
		//Vertex data
		helper.WriteVertices(fi, write.vertexCount, write.vertices);
		//Index data
		helper.WriteIndices(fi, write.indexCount, write.indices);
		fclose(fi);
		break;
	case 1:
		printf("input: ");
		std::cin >> input;
		printf("Output: ");
		std::cin >> output;
		fi = fopen(input, "rb");
		if (!fi)
			return -1;
		int temp;
		fscanf(fi, "NrVertices: %d\n", &vertexCount);
		vertices = new Vertex[vertexCount];
		for (FWuint i = 0; i < vertexCount; i++)
		{
			Vertex vt;
			fscanf(fi, "%d. ", &temp);
			vt.Position = helper.ReadVector3(fi, "pos:[%f,%f,%f]; ");
			vt.Normal = helper.ReadVector3(fi, "norm:[%f,%f,%f]; ");
			vt.BiNormal = helper.ReadVector3(fi, "binorm:[%f,%f,%f]; ");
			vt.Tangent = helper.ReadVector3(fi, "tgt:[%f,%f,%f]; ");
			vt.Coordinate = helper.ReadVector2(fi, "uv:[%f,%f];\n");
			vertices[i] = vt;
		}
		fscanf(fi, "NrIndices: %d\n", &indexCount);
		indices = new FWuint[indexCount];
		for (FWuint i = 0; i < indexCount; i += 3)
		{
			fscanf(fi, "%d. %d, %d, %d\n", &temp, &indices[i], &indices[i + 1], &indices[i + 2]);
		}
		fclose(fi);

		fo = fopen(output, "wb");
		if (!fo)
			return -1;
		helper.WriteVertices(fo, vertexCount, vertices);
		helper.WriteIndices(fo, indexCount, indices);

		fclose(fo);
		break;
	default:
		break;
	}
	printf("write end\n");
	_getch();
	return 0;
};